package win.smartown.kotlin.`class`

//类可以包含：
// 构造函数和初始化代码块
// 函数
// 属性
// 内部类
// 对象声明

//继承
// 所有类都有共同的父类Any
open class Base(name: String) //隐式继承于Any

//声明一个明确的父类，需要在类后面加:再加父类
class Sub(name: String) : Base(name)

//如果类有主构造函数，则基类可以而且是必须在主构造函数中立即初始化。
//如果类没有主构造函数，则必须在每一个构造函数中用super关键字初始化基类，
//或者在代理另一个代理另一个构造函数这件事。
//在这种情形中不同的二级构造函数可以调用基类不同的构造方法。
open class BaseClass {
    constructor(i: Int)
    constructor(i: Int, s: String)
}

class SubClass : BaseClass {
    constructor(i: Int) : super(i)
    constructor(i: Int, s: String) : super(i, s)
}

open class Super {
    open fun fun1(): Unit {}
    fun fun2(): Unit {}
}

open class SuperSub : Super() {
    open override fun fun1() {
        super.fun1()
    }
}

class AnotherSuperSub : SuperSub() {
    override fun fun1() {
        super.fun1()
    }
}


open class A {
    open fun say(): Unit {
        println("A say.")
    }
}

interface B {
    //接口成员默认是open的
    fun say(): Unit {
        println("B say.")
    }
}

class C : A(), B {
    override fun say() {
        super<A>.say()
        super<B>.say()
    }
}

fun main(args: Array<String>) {
    C().say()
    println(eval(Expr.Const(12.0)))
    println(eval(Expr.Sum(Expr.Const(12.0), Expr.Const(12.0))))
}

//abstract修饰的类或成员默认是open的
abstract class AbstractClass : A() {
    abstract override fun say()
}

class SubAbstractClass : AbstractClass() {
    override fun say() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

//密封类
//密封类用于代表严格的类结构，值只能是有限集合中的某种类型，不可以是任何其他类型。
//声明密封类加sealed修饰符。密封类可以有子类但必须全部嵌套在密封类声明内部
sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}

fun eval(expr: Expr): Double = when (expr) {
    is Expr.Const -> expr.number
    is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
    Expr.NotANumber -> Double.NaN
}